﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Noris.Tools.DbManager.Components
{
	/// <summary>
	/// Třída extenzí pro grafické class
	/// </summary>
	public static class DrawingExtensions
	{
		#region Color: ShiftColor
		public static Color ShiftColor(this Color root, float shift)
        {
            float r = (float)root.R + shift;
            float g = (float)root.G + shift;
            float b = (float)root.B + shift;
            return GetColor(root.A, r, g, b);
        }
        public static Color ShiftColor(this Color root, float shiftR, float shiftG, float shiftB)
        {
            float r = (float)root.R + shiftR;
            float g = (float)root.G + shiftG;
            float b = (float)root.B + shiftB;
            return GetColor(root.A, r, g, b);
        }
        public static Color ShiftColor(this Color root, float shiftA, float shiftR, float shiftG, float shiftB)
        {
            float a = (float)root.A + shiftA;
            float r = (float)root.R + shiftR;
            float g = (float)root.G + shiftG;
            float b = (float)root.B + shiftB;
            return GetColor(a, r, g, b);
        }
        private static Color GetColor(float a, float r, float g, float b)
        {
            int ac = (a < 0f ? 0 : (a > 255f ? 255 : (int)a));
            int rc = (r < 0f ? 0 : (r > 255f ? 255 : (int)r));
            int gc = (g < 0f ? 0 : (g > 255f ? 255 : (int)g));
            int bc = (b < 0f ? 0 : (b > 255f ? 255 : (int)b));
            return Color.FromArgb(ac, rc, gc, bc);
        }
		#endregion
		#region Point, PointF: Relative/Absolute
		/// <summary>
        /// Vrátí relativní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
        /// </summary>
        /// <param name="absolutePoint"></param>
        /// <param name="basePoint"></param>
        /// <returns></returns>
        public static Point GetRelativePointFromBase(this Point absolutePoint, Point basePoint)
        {
            return new Point(absolutePoint.X - basePoint.X, absolutePoint.Y - basePoint.Y);
        }
        /// <summary>
        /// Vrátí absolutní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
        /// </summary>
        /// <param name="point"></param>
        /// <param name="relativePoint"></param>
        /// <returns></returns>
        public static Point GetAbsolutePointFromBase(this Point point, Point relativePoint)
        {
            return new Point(relativePoint.X + point.X, relativePoint.Y + point.Y);
        }
		/// <summary>
		/// Vrátí relativní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
		/// </summary>
		/// <param name="absolutePoint"></param>
		/// <param name="basePoint"></param>
		/// <returns></returns>
		public static PointF GetRelativePointFromBase(this Point absolutePoint, PointF basePoint)
		{
			return new PointF((float)absolutePoint.X - basePoint.X, (float)absolutePoint.Y - basePoint.Y);
		}
		/// <summary>
		/// Vrátí absolutní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
		/// </summary>
		/// <param name="point"></param>
		/// <param name="relativePoint"></param>
		/// <returns></returns>
		public static PointF GetAbsolutePointFromBase(this Point point, PointF relativePoint)
		{
			return new PointF((float)relativePoint.X + point.X, (float)relativePoint.Y + point.Y);
		}
		/// <summary>
		/// Vrátí relativní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
		/// </summary>
		/// <param name="absolutePoint"></param>
		/// <param name="basePoint"></param>
		/// <returns></returns>
		public static PointF GetRelativePointFromBase(this PointF absolutePoint, PointF basePoint)
		{
			return new PointF(absolutePoint.X - basePoint.X, absolutePoint.Y - basePoint.Y);
		}
		/// <summary>
		/// Vrátí absolutní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
		/// </summary>
		/// <param name="point"></param>
		/// <param name="relativePoint"></param>
		/// <returns></returns>
		public static PointF GetAbsolutePointFromBase(this PointF point, PointF relativePoint)
		{
			return new PointF(relativePoint.X + point.X, relativePoint.Y + point.Y);
		}
		/// <summary>
		/// Vrátí relativní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
		/// </summary>
		/// <param name="absolutePoint"></param>
		/// <param name="basePoint"></param>
		/// <returns></returns>
		public static Point GetRelativePointFromBase(this PointF absolutePoint, Point basePoint)
		{
			return Point.Round(new PointF(absolutePoint.X - (float)basePoint.X, absolutePoint.Y - (float)basePoint.Y));
		}
		/// <summary>
		/// Vrátí absolutní bod pro souřadnice bodu this, pokud by počátek byl v daném bodě basePoint.
		/// </summary>
		/// <param name="point"></param>
		/// <param name="relativePoint"></param>
		/// <returns></returns>
		public static Point GetAbsolutePointFromBase(this PointF point, Point relativePoint)
		{
			return Point.Round(new PointF((float)relativePoint.X + point.X, (float)relativePoint.Y + point.Y));
		}
		#endregion
		#region RectangleF: FromPoint, FromDim
		/// <summary>
        /// Vrátí RectangleF, který je natažený mezi dvěma body, přičemž vzájemná pozice oněch dvou bodů může být libovolná.
        /// </summary>
        /// <param name="point1"></param>
        /// <param name="point2"></param>
        /// <returns></returns>
        public static RectangleF GetRectangleFFromPoints(this PointF point1, PointF point2)
        {
            float l = (point1.X < point2.X ? point1.X : point2.X);
            float t = (point1.Y < point2.Y ? point1.Y : point2.Y);
            float r = (point1.X > point2.X ? point1.X : point2.X);
            float b = (point1.Y > point2.Y ? point1.Y : point2.Y);
            return RectangleF.FromLTRB(l, t, r, b);
        }
		/// <summary>
		/// Vrátí RectangleF, který je nakreslený mezi souřadnicemi x1÷x2 a y1÷y2.
		/// </summary>
		/// <param name="point1"></param>
		/// <param name="point2"></param>
		/// <returns></returns>
		public static RectangleF GetRectangleFFromDim(float x1, float x2, float y1, float y2)
		{
			float l = (x1 < x2 ? x1 : x2);
			float t = (y1 < y2 ? y1 : y2);
			float r = (x1 > x2 ? x1 : x2);
			float b = (y1 > y2 ? y1 : y2);
			return RectangleF.FromLTRB(l, t, r, b);
		}
		/// <summary>
		/// Vrátí RectangleF, který je nakreslený mezi souřadnicemi x1÷x2 a y1÷y2.
		/// Pokud je vzdálenost mezi x1÷x2 nebo y1÷y2 menší než minDist, pak zachová vzdálenost minDist,
		/// a to tak, že v odpovídajícím směru upraví souřadnici x2 nebo y2. 
		/// Jako x2/y2 by tedy měla být zadána ta "pohyblivější".
		/// </summary>
		/// <returns></returns>
		public static RectangleF GetRectangleFFromDim(float x1, float x2, float y1, float y2, float minDist)
		{
			// Úprava souřadnic minDist (kladné číslo) a x2,y2:
			if (minDist < 0f) minDist = -minDist;
			if (x2 >= x1 && x2 - x1 < minDist)
				x2 = x1 + minDist;
			else if (x2 < x1 && x1 - x2 < minDist)
				x2 = x1 - minDist;
			if (y2 >= y1 && y2 - y1 < minDist)
				y2 = y1 + minDist;
			else if (y2 < y1 && y1 - y2 < minDist)
				y2 = y1 - minDist;

			float l = (x1 < x2 ? x1 : x2);
			float t = (y1 < y2 ? y1 : y2);
			float r = (x1 > x2 ? x1 : x2);
			float b = (y1 > y2 ? y1 : y2);
			return RectangleF.FromLTRB(l, t, r, b);
		}
		#endregion
	}
	#region class SysCursors, enum SysCursorType
	/// <summary>
	/// Práce s objekty Cursor
	/// </summary>
	internal class SysCursors
	{
		public static Cursor GetCursor(SysCursorType cursorType)
		{
			switch (cursorType)
			{
				case SysCursorType.AppStarting: return Cursors.AppStarting;
				case SysCursorType.Arrow: return Cursors.Arrow;
				case SysCursorType.Cross: return Cursors.Cross;
				case SysCursorType.Default: return Cursors.Default;
				case SysCursorType.Hand: return Cursors.Hand;
				case SysCursorType.Help: return Cursors.Help;
				case SysCursorType.HSplit: return Cursors.HSplit;
				case SysCursorType.IBeam: return Cursors.IBeam;
				case SysCursorType.No: return Cursors.No;
				case SysCursorType.NoMove2D: return Cursors.NoMove2D;
				case SysCursorType.NoMoveHoriz: return Cursors.NoMoveHoriz;
				case SysCursorType.NoMoveVert: return Cursors.NoMoveVert;
				case SysCursorType.PanEast: return Cursors.PanEast;
				case SysCursorType.PanNE: return Cursors.PanNE;
				case SysCursorType.PanNorth: return Cursors.PanNorth;
				case SysCursorType.PanNW: return Cursors.PanNW;
				case SysCursorType.PanSE: return Cursors.PanSE;
				case SysCursorType.PanSouth: return Cursors.PanSouth;
				case SysCursorType.PanSW: return Cursors.PanSW;
				case SysCursorType.PanWest: return Cursors.PanWest;
				case SysCursorType.SizeAll: return Cursors.SizeAll;
				case SysCursorType.SizeNESW: return Cursors.SizeNESW;
				case SysCursorType.SizeNS: return Cursors.SizeNS;
				case SysCursorType.SizeNWSE: return Cursors.SizeNWSE;
				case SysCursorType.SizeWE: return Cursors.SizeWE;
				case SysCursorType.UpArrow: return Cursors.UpArrow;
				case SysCursorType.VSplit: return Cursors.VSplit;
				case SysCursorType.WaitCursor: return Cursors.WaitCursor;
			}
			return Cursors.Default;
		}
	}
	public enum SysCursorType
	{
		/// <summary>No change (žádná změna)</summary>
		Null = 0,
		/// <summary>cursor that appears when an application starts.</summary>
		AppStarting,
		/// <summary>arrow cursor.</summary>
		Arrow,
		/// <summary>crosshair cursor.</summary>
		Cross,
		/// <summary>default cursor, which is usually an arrow cursor.</summary>
		Default,
		/// <summary>hand cursor, typically used when hovering over a Web link.</summary>
		Hand,
		/// <summary>Help cursor, which is a combination of an arrow and a question mark.</summary>
		Help,
		/// <summary>cursor that appears when the mouse is positioned over a horizontal splitter bar.</summary>
		HSplit,
		/// <summary>I-beam cursor, which is used to show where the text cursor appears when the mouse is clicked.</summary>
		IBeam,
		/// <summary>cursor that indicates that a particular region is invalid for the current operation.</summary>
		No,
		/// <summary>cursor that appears during wheel operations when the mouse is not moving, but the window can be scrolled in both a horizontal and vertical direction.</summary>
		NoMove2D,
		/// <summary>cursor that appears during wheel operations when the mouse is not moving, but the window can be scrolled in a horizontal direction.</summary>
		NoMoveHoriz,
		/// <summary>cursor that appears during wheel operations when the mouse is not moving, but the window can be scrolled in a vertical direction.</summary>
		NoMoveVert,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling horizontally to the right.</summary>
		PanEast,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling horizontally and vertically upward and to the right.</summary>
		PanNE,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling vertically in an upward direction.</summary>
		PanNorth,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling horizontally and vertically upward and to the left.</summary>
		PanNW,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling horizontally and vertically downward and to the right.</summary>
		PanSE,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling vertically in a downward direction.</summary>
		PanSouth,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling horizontally and vertically downward and to the left.</summary>
		PanSW,
		/// <summary>cursor that appears during wheel operations when the mouse is moving and the window is scrolling horizontally to the left.</summary>
		PanWest,
		/// <summary>four-headed sizing cursor, which consists of four joined arrows that point north, south, east, and west.</summary>
		SizeAll,
		/// <summary>two-headed diagonal (northeast/southwest) sizing cursor.</summary>
		SizeNESW,
		/// <summary>two-headed vertical (north/south) sizing cursor.</summary>
		SizeNS,
		/// <summary>two-headed diagonal (northwest/southeast) sizing cursor.</summary>
		SizeNWSE,
		/// <summary>two-headed horizontal (west/east) sizing cursor.</summary>
		SizeWE,
		/// <summary>up arrow cursor, typically used to identify an insertion point.</summary>
		UpArrow,
		/// <summary>cursor that appears when the mouse is positioned over a vertical splitter bar.</summary>
		VSplit,
		/// <summary>wait cursor, typically an hourglass shape.</summary>
		WaitCursor
	}
	#endregion
}
